//神麤詭末，2682963017，与君共勉之。
"nodejs";
const path = require('path');
const fs = require('fs');
var storagesPath;
try {
    const $java = $autojs.java;
    const ctx = $autojs.androidContext;
    storagesPath = ctx.getFilesDir().getAbsolutePath() + "/";
} catch (e) {

}


class MetaKey {
    constructor(key, index, size = 5000) {
        this.key = key;
        this.index = index;
        this.size = size;
    }
}
class Storages {
    static instance = {};
    static create(location, maxSize = 5 * 1024) {
        return new Storages(location, maxSize);
    }
    maxSize;
    metaKeyMap;
    location;
    keys;
    bytesInUse;
    length;
    constructor(location, maxSize = 5 * 1024) {
        if (Storages.instance[location]) {
            return Storages.instance[location];
        }
        Storages.instance[location] = this;
        this.metaKeyMap = Object.create(null);
        this.keys = [];
        this.location = `${storagesPath}${location}`;
        this.maxSize = maxSize;
        this.bytesInUse = 0;
        this.length = 0;
        this.init();
    }
    init() {
        try {
            if (!fs.existsSync(this.location)) {
                fs.mkdirSync(this.location);
            }
            const storeStat = this.getStat();
            if (storeStat && !storeStat.isDirectory()) {
                fs.rmSync(this.location);
                throw new Error('location路径必须是目录');
            }
            const keys = fs.readdirSync(this.location);
            keys.forEach((key, index) => {
                const decodedKey = decodeURIComponent(key);
                this.keys.push(decodedKey);
                const stat = this.getStat(key);
                this.metaKeyMap[decodedKey] = new MetaKey(key, index, stat.size);
                this.bytesInUse += stat.size;
            });
            this.length = keys.length;
        } catch (e) {
            throw e;
        }
    }
    getStat(key = '') {
        const filename = path.join(this.location, encodeURIComponent(key));
        try {
            return fs.statSync(filename);
        } catch {
            return null;
        }
    }
    setItem(key, value) {
        const encodedKey = encodeURIComponent(key).replace(/[!'()]/g, escape).replace(/\*/g, '%2A');
        const valueString = JSON.stringify(value);
        const valueStringLength = valueString.length;
        const metaKey = this.metaKeyMap[key];
        const oldLength = metaKey?.size || 0;
        const lengthChange = valueStringLength - oldLength;
        if (this.bytesInUse + lengthChange > this.maxSize) {
            throw new Error('超过最大大小限制！');
        }
        const filename = path.join(this.location, encodedKey);
        fs.writeFileSync(filename, valueString, {
            encoding: 'utf-8'
        });
        if (!metaKey) {
            this.metaKeyMap[key] = new MetaKey(encodedKey, this.keys.push(key) - 1, valueString.length);
            this.length += 1;
        }
        this.bytesInUse += lengthChange;
    }
    getItem(key, default_value) {
        const metaKey = this.metaKeyMap[key];
        if (!!metaKey) {
            const filename = path.join(this.location, metaKey.key);
            return JSON.parse(fs.readFileSync(filename, 'utf-8'));
        }
        return default_value;
    }
    containsItem(key){
        return this.getItem(key) ? true : false;
    }
    removeItem(key) {
        const metaKey = this.metaKeyMap[key];
        if (metaKey) {
            delete this.metaKeyMap[key];
            this.length -= 1;
            this.bytesInUse -= metaKey.size || 0;
            this.keys.splice(metaKey.index, 1);
            for (const k in this.metaKeyMap) {
                const meta = this.metaKeyMap[k];
                if (meta.index > metaKey.index) {
                    meta.index -= 1;
                }
            }
            rm(path.join(this.location, metaKey.key));
        }
    }
    put(key, value){
        this.setItem(key, value);
    }
    set(key, value){
        this.setItem(key, value);
    }
    get(key, default_value){
        return this.getItem(key, default_value);
    }
    key(n) {
        return this.keys[n] ?? null;
    }
    contains(key){
        return this.containsItem(key);
    }
    remove(key){
        this.removeItem(key);
    }
    clear() {
        emptyDirectory(this.location);
        this.metaKeyMap = Object.create(null);
        this.keys = [];
        this.length = 0;
        this.bytesInUse = 0;
    }
}

function emptyDirectory(target) {
    for (const p of fs.readdirSync(target)) {
        rm(path.join(target, p));
    }
    fs.rmdirSync(target);
}

function rm(target) {
    if (fs.statSync(target).isDirectory()) {
        emptyDirectory(target);
    }
    else {
        fs.unlinkSync(target);
    }
}
module.exports = Storages;